__author__ = 'huberg'
try:
    import xml.etree.cElementTree as ET
except ImportError:
    import xml.etree.ElementTree as ET

import optparse

def load_net(fname):
    tree = ET.ElementTree(file=fname)
    root = tree.getroot()
    edge_set = {}
    for node in root:
        if node.tag == 'edge':
            edge_id = node.attrib['id']
            length = 0
            speed = 0
            nlane = 0
            for child in node:
                if child.tag == 'lane':
                    length = float(child.attrib['length'])
                    speed = float(child.attrib['speed'])
                    nlane += 1
            edge_set.setdefault(edge_id, {'speed': speed, 'length': length, 'nlane':nlane})
    return edge_set


def load_route(fname, handler):
    assert isinstance(handler, RoadAnalyser)
    tree = ET.ElementTree(file=fname)
    root = tree.getroot()
    for node in root:
        if node.tag == 'vehicle':
            trip = [None] * 4
            trip[0] = node.attrib['id']
            trip[1] = node.attrib['type']
            trip[2] = int(float(node.attrib['depart']))
            routes = node[0].attrib['edges']
            routes = routes.split()
            trip[3] = routes
            handler.process(trip)
            del routes

class RoadAnalyser:
    def __init__(self, net_file, avg_speed):
        self.edge_set = load_net(net_file)
        self.demand = {}
        self.focus = None
        self.speed = avg_speed
        self.delay = 10
        pass

    def register(self, edge_id):
        self.focus = edge_id

    def process(self, trip):
        # trip format : ['id', 'type', 'depart',[edges...]]
        assert len(trip) == 4
        assert isinstance(trip[3], list)
        if self.focus in trip[3]:
            # calcuate time of into the road and depart time
            driving_time = 0
            for edge_id in trip[3]:
                if edge_id == self.focus:
                    break
                if edge_id in self.edge_set:
                    length = self.edge_set[edge_id]['length']
                    driving_time += length / self.speed + self.delay
                else:
                    print("trip: vehicle {0} drove in edge {1} which is not in the map".format(trip[0], edge_id))
                    # logging.error("trip : vehicle {0} drove in edge {1} which is not in the map".format(trip[0], edge_id))
                    return
            arrive_time = int(trip[2] + driving_time)
            self.demand.setdefault(arrive_time, 0)
            self.demand[arrive_time] += 1
            depart_time = int(trip[2] + driving_time + self.edge_set[self.focus]['length'] / self.speed)
            self.demand.setdefault(depart_time, 0)
            self.demand[depart_time] -= 1

    def write_to_file(self, fname):

        capacity = sorted(self.demand.iteritems(), key=lambda d: d[0], reverse=False)
        for i in range(len(capacity)):
            if i + 1 < len(capacity):
                capacity[i + 1] = (capacity[i + 1][0], capacity[i + 1][1] + capacity[i][1])

        with open(fname, "wb") as f:
            f.write("time,number\n")
            for item in capacity:
                f.write("{0},{1}\n".format(item[0],item[1]))

        del capacity

def get_options(args=None):
    parser = optparse.OptionParser()
    parser.add_option("-n", "--net-file", dest="net_file", help="network file")
    parser.add_option("-r", "--route-file", dest="route_file", help="Trips file")
    parser.add_option("-o", "--output-file", dest="output_file", help="Output File")
    parser.add_option("-e", "--edge-id", dest="edge_id", help="The observed edge")
    parser.add_option("-v", "--velocity", type='float', dest="velocity", help="The specified speed in every road")
    parser.add_option("-l", "--log-file", dest="log_file", help="The log file")
    (options, args) = parser.parse_args(args=args)

    if not options.net_file or not options.route_file or not options.output_file or not options.edge_id or not options.velocity:
        parser.print_help()
        exit(1)
    if not options.log_file:
        options.log_file = "log_file.txt"
    return options

def main(options=None):
    # logging.basicConfig(level=logging.INFO, format="%(message)s", filename=options.log_file, filemode="a")
    analyser = RoadAnalyser(options.net_file, options.velocity)
    analyser.register(options.edge_id)
    load_route(options.route_file, analyser)
    analyser.write_to_file(options.output_file)


if __name__ == '__main__':
    main(get_options())